﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Data;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Input;
using System.Xml;
using Epi;
using Epi.Data;
using Epi.Fields;
using Epi.ImportExport;
using Epi.ImportExport.Filters;
using Epi.ImportExport.ProjectPackagers;
using Menafrinet.Core;
using Menafrinet.ViewModel;
using Menafrinet.ViewModel.Events;
using Menafrinet.ViewModel.Locations;

namespace Menafrinet.ViewModel
{
    /// <summary>
    /// Data helper class for the Menafrinet application
    /// </summary>
    public class DataHelper : DataHelperBase
    {
        #region Members
        private ObservableCollection<CaseViewModel> _caseCollection = new ObservableCollection<CaseViewModel>();
        private ObservableCollection<CaseViewModel> _filteredCaseCollection = new ObservableCollection<CaseViewModel>();
        private ObservableCollection<SiteMergeStatusViewModel> _siteCollection = new ObservableCollection<SiteMergeStatusViewModel>();
        private ObservableCollection<ISiteType> _siteTypes = new ObservableCollection<ISiteType>();
        private string _searchString = String.Empty;
        private System.Windows.Shell.TaskbarItemProgressState _taskbarProgressState = System.Windows.Shell.TaskbarItemProgressState.Indeterminate;
        private double _taskbarProgressValue = 0.0;
        #endregion

        #region Properties
        /// <summary>
        /// Gets whether any of the cases in the system contain invalid EPID values.
        /// </summary>
        public bool ContainsInvalidEpids
        {
            get
            {
                foreach (CaseViewModel caseVM in CaseCollection)
                {
                    if (caseVM.FlagEPIDAsInvalid == true && caseVM.RecStatus == 1)
                    {
                        return true;
                    }
                }
                return false;
            }
        }

        /// <summary>
        /// Gets whether any of the cases in the system have duplicate EPID values.
        /// </summary>
        public bool ContainsDuplicateCases
        {
            get
            {
                foreach (CaseViewModel caseVM in CaseCollection)
                {
                    if (caseVM.FlagAsDuplicate == true && caseVM.RecStatus == 1)
                    {
                        return true;
                    }
                }
                return false;
            }
        }

        /// <summary>
        /// Gets/sets the current search string
        /// </summary>
        public string SearchString
        {
            get
            {
                return this._searchString;
            }
            set
            {
                if (this._searchString != value)
                {
                    this._searchString = value;
                    RaisePropertyChanged("SearchString");
                    Search(SearchString);
                }
            }
        }

        /// <summary>
        /// Gets/sets the current progress value for the progress bar that shows up in the app's taskbar icon.
        /// </summary>
        public double TaskbarProgressValue
        {
            get
            {
                return this._taskbarProgressValue;
            }
            set
            {
                if (this._taskbarProgressValue != value)
                {
                    this._taskbarProgressValue = value;
                    RaisePropertyChanged("TaskbarProgressValue");
                }
            }
        }

        /// <summary>
        /// Gets/sets the current progress state for the progress bar that shows up in the app's taskbar icon.
        /// </summary>
        public System.Windows.Shell.TaskbarItemProgressState TaskbarProgressState
        {
            get
            {
                return this._taskbarProgressState;
            }
            set
            {
                if (this._taskbarProgressState != value)
                {
                    this._taskbarProgressState = value;
                    RaisePropertyChanged("TaskbarProgressState");
                }
            }
        }

        public View ContactForm { get; set; }
        private XmlDocument SiteXmlData { get; set; }
        public ObservableCollection<CaseViewModel> CaseCollection
        {
            get
            {
                return this._caseCollection;
            }
            private set
            {
                if (this._caseCollection != value)
                {
                    this._caseCollection = value;
                    RaisePropertyChanged("CaseCollection");
                }
            }
        }

        public ObservableCollection<SiteMergeStatusViewModel> SiteCollection
        {
            get
            {
                return this._siteCollection;
            }
            private set
            {
                if (this._siteCollection != value)
                {
                    this._siteCollection = value;
                    RaisePropertyChanged("SiteCollection");
                }
            }
        }

        public ObservableCollection<CaseViewModel> FilteredCaseCollection
        {
            get
            {
                return this._filteredCaseCollection;
            }
            private set
            {
                if (this._filteredCaseCollection != value)
                {
                    this._filteredCaseCollection = value;
                    RaisePropertyChanged("FilteredCaseCollection");
                }
            }
        }

        public ObservableCollection<ISiteType> SiteTypes
        {
            get
            {
                return this._siteTypes;
            }
            private set
            {
                if (this._siteTypes != value)
                {
                    this._siteTypes = value;
                    RaisePropertyChanged("SiteTypes");
                }
            }
        }

        public string LastSearchTerm { get; private set; }

        public string ProjectPath
        {
            get
            {
                return this.Project.FilePath; // verify this
            }
            set
            {
                this.Project = new Project(value);
                RaisePropertyChanged("ProjectPath");
            }
        }
        #endregion // Properties

        #region Delegates
        public delegate void CaseDataPopulatedHandler(object sender, CaseDataPopulatedArgs e);
        public delegate void InitialSetupRunHandler(object sender, EventArgs e);
        public delegate void InvalidIdDetectedHandler(object sender, InvalidIdDetectedArgs e);
        public delegate void CaseDeletedHandler(object sender, CaseDeletedArgs e);
        public delegate void DuplicateIdDetectedHandler(object sender, DuplicateIdDetectedArgs e);
        #endregion // Delegates

        #region Events
        public event InitialSetupRunHandler InitialSetupRun;
        public event CaseDataPopulatedHandler CaseDataPopulated;
        public event InvalidIdDetectedHandler InvalidIdDetected;
        //public event CaseDeletedHandler CaseDeleted; // Not implemented at this time
        public event DuplicateIdDetectedHandler DuplicateIdDetected;
        #endregion // Events

        #region Constructors
        /// <summary>
        /// Constructor
        /// </summary>
        public DataHelper()
        {
            if (LoadConfig())
            {
                LastSearchTerm = String.Empty;
                TaskbarProgressState = System.Windows.Shell.TaskbarItemProgressState.Indeterminate;
            }
        }
        #endregion // Constructors

        private void Search(string inputSearchString)
        {
            inputSearchString = inputSearchString.ToLower();

            LastSearchTerm = inputSearchString;

            FilteredCaseCollection.Clear();

            if (String.IsNullOrEmpty(inputSearchString.Trim()))
            {
                foreach (CaseViewModel caseVM in CaseCollection)
                {
                    FilteredCaseCollection.Add(caseVM);
                }
            }
            else
            {
                inputSearchString = inputSearchString.Replace(" =", "=").Replace("= ", "=").Replace(" = ", "=");

                string[] termsArray = inputSearchString.Split(' ');

                int count = 0;

                foreach (CaseViewModel caseVM in CaseCollection)
                {
                    count++;
                    Type t = caseVM.GetType();
                    foreach (PropertyInfo propertyInfo in t.GetProperties())
                    {
                        if (propertyInfo.CanRead)
                        {
                            object value = propertyInfo.GetValue(caseVM, null);

                            if (value == null)
                            {
                                value = String.Empty;
                            }

                            string name = propertyInfo.Name.ToLower();

                            foreach (string term in termsArray)
                            {
                                if (term.ToLower().Equals(value.ToString().ToLower()))
                                {
                                    if (!FilteredCaseCollection.Contains(caseVM))
                                    {
                                        FilteredCaseCollection.Add(caseVM);
                                    }
                                }
                                else if (term.ToLower().Contains("*") && MatchWildcardString(term.ToLower(), value.ToString().ToLower()))
                                {
                                    if (!FilteredCaseCollection.Contains(caseVM))
                                    {
                                        FilteredCaseCollection.Add(caseVM);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        public bool MatchWildcardString(string pattern, string input)
        {
            if (String.Compare(pattern, input) == 0)
            {
                return true;
            }
            else if (String.IsNullOrEmpty(input))
            {
                if (String.IsNullOrEmpty(pattern.Trim(new Char[1] { '*' })))
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else if (pattern.Length == 0)
            {
                return false;
            }
            else if (pattern[0] == '?')
            {
                return MatchWildcardString(pattern.Substring(1), input.Substring(1));
            }
            else if (pattern[pattern.Length - 1] == '?')
            {
                return MatchWildcardString(pattern.Substring(0, pattern.Length - 1), input.Substring(0, input.Length - 1));
            }
            else if (pattern[0] == '*')
            {
                if (MatchWildcardString(pattern.Substring(1), input))
                {
                    return true;
                }
                else
                {
                    return MatchWildcardString(pattern, input.Substring(1));
                }
            }
            else if (pattern[pattern.Length - 1] == '*')
            {
                if (MatchWildcardString(pattern.Substring(0, pattern.Length - 1), input))
                {
                    return true;
                }
                else
                {
                    return MatchWildcardString(pattern, input.Substring(0, input.Length - 1));
                }
            }
            else if (pattern[0] == input[0])
            {
                return MatchWildcardString(pattern.Substring(1), input.Substring(1));
            }
            return false;
        }

        /// <summary>
        /// Used to repopulate all collections. This is an expensive process and should only be called when absolutely necessary.
        /// </summary>
        public override void RepopulateCollections()
        {
            SetupDatabase();
            ClearCollections();
            PopulateCollections();
            //Task.Factory.StartNew(PopulateCollections, System.Threading.CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.FromCurrentSynchronizationContext());
        }

        /// <summary>
        /// Used to clear all case, contact, and link objects from memory.
        /// </summary>
        protected override void ClearCollections()
        {
            CaseCollection.Clear(); // = new ObservableCollection<CaseViewModel>();
            FilteredCaseCollection.Clear(); // = new ObservableCollection<CaseViewModel>();
        }

        /// <summary>
        /// Used to get a list of all duplicate cases, using the EPID field as the match value.
        /// </summary>
        /// <returns></returns>
        private List<CaseViewModel> GetDuplicateCasesBasedOnID()
        {
            List<CaseViewModel> duplicates = new List<CaseViewModel>();
            foreach (CaseViewModel iCaseVM in CaseCollection)
            {
                UnflagCaseAsDuplicate(iCaseVM);
                string iID = iCaseVM.EPID;

                foreach (CaseViewModel jCaseVM in CaseCollection)
                {
                    if (jCaseVM != iCaseVM)
                    {
                        string jID = jCaseVM.EPID;

                        if (jID.Equals(iID))
                        {
                            if (!duplicates.Contains(iCaseVM) && !duplicates.Contains(jCaseVM) && !String.IsNullOrEmpty(jID))
                            {
                                duplicates.Add(iCaseVM);
                                FlagCaseAsDuplicate(iCaseVM);
                                FlagCaseAsDuplicate(jCaseVM);
                            }
                        }
                    }
                }

                if (String.IsNullOrEmpty(iID))
                {
                    FlagCaseAsInvalidEpid(iCaseVM);
                }
            }

            return duplicates;
        }

        /// <summary>
        /// Used to flag duplicate records based on EPID
        /// </summary>
        /// <returns></returns>
        private void FlagDuplicateRecords()
        {
            foreach (CaseViewModel iCaseVM in CaseCollection)
            {
                string iID = iCaseVM.EPID;

                foreach (CaseViewModel jCaseVM in CaseCollection)
                {
                    if (jCaseVM != iCaseVM)
                    {
                        string jID = jCaseVM.EPID;

                        if (jID.Equals(iID))
                        {
                            if (!String.IsNullOrEmpty(jID))
                            {
                                FlagCaseAsDuplicate(iCaseVM);
                                FlagCaseAsDuplicate(jCaseVM);
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Flags a given case as having an invalid EPID
        /// </summary>
        /// <param name="caseVM">The case to flag as having an invalid EPID</param>
        private void FlagCaseAsInvalidEpid(CaseViewModel caseVM)
        {
            caseVM.FlagEPIDAsInvalid = true; // bad; move this to the case model at some point
        }

        /// <summary>
        /// Flags a given case as being a duplicate record
        /// </summary>
        /// <param name="caseVM">The case to flag as being a duplicate</param>
        private void FlagCaseAsDuplicate(CaseViewModel caseVM)
        {
            caseVM.FlagAsDuplicate = true;
        }

        /// <summary>
        /// Unflags a given case as being a duplicate record
        /// </summary>
        /// <param name="caseVM">The case to flag as being a duplicate</param>
        private void UnflagCaseAsDuplicate(CaseViewModel caseVM)
        {
            caseVM.FlagAsDuplicate = false;
        }

        /// <summary>
        /// Loads data from a given data row into the given case view model
        /// </summary>
        /// <param name="row">The row that contains the data to be loaded</param>
        /// <param name="c">The case view model whose fields will be updated</param>
        private void LoadCaseData(DataRow row, CaseViewModel c)
        {
            double? ageYears = null;
            double? ageMonths = null;
            double? year = null;

            if (!String.IsNullOrEmpty(row["Annee"].ToString()))
            {
                year = double.Parse(row["Annee"].ToString());
                c.Year = Math.Truncate(year.Value);
            }
            if (!String.IsNullOrEmpty(row["Agean"].ToString()))
            {                
                ageYears = double.Parse(row["Agean"].ToString());
                c.AgeYears = Math.Truncate(ageYears.Value);
            }
            if (!String.IsNullOrEmpty(row["Agemois"].ToString()))
            {
                ageMonths = double.Parse(row["Agemois"].ToString());
                c.AgeMonths = Math.Truncate(ageMonths.Value);
            }

            c.Age = ageYears;

            if (c.Age.HasValue && ageMonths.HasValue)
            {
                c.Age = c.Age.Value + (ageMonths.Value / 12);
            }
            else if (!c.Age.HasValue && ageMonths.HasValue)
            {
                c.Age = (ageMonths.Value / 12);
            }

            if (c.Age.HasValue)
            {
                c.Age = Math.Truncate(c.Age.Value);
            }

            c.RecStatus = 1;

            if (row["RecStatus"] != DBNull.Value)
            {
                c.RecStatus = byte.Parse(row["RecStatus"].ToString());
            }

            c.City = row["Ville"].ToString();
            c.Classification = row["Classificationfinale"].ToString();

            if (!String.IsNullOrEmpty(row["DateDebut"].ToString()))
            {
                c.DateOnset = DateTime.Parse(row["DateDebut"].ToString());
            }

            c.FinalLabResult = row["ResultatFinalLNR"].ToString();
            c.Outcome = row["Evolution"].ToString().Trim();

            switch (row["Evolution"].ToString().Trim())
            {
                case "1":
                    if (System.Threading.Thread.CurrentThread.CurrentCulture.ToString().ToLower().Equals("fr-fr"))
                    {
                        c.Outcome = "Vivant";
                    }
                    else if (System.Threading.Thread.CurrentThread.CurrentCulture.ToString().ToLower().Equals("en-us"))
                    {
                        c.Outcome = "Alive";
                    }
                    break;
                case "2":
                    if (System.Threading.Thread.CurrentThread.CurrentCulture.ToString().ToLower().Equals("fr-fr"))
                    {
                        c.Outcome = "Décédé";
                    }
                    else if (System.Threading.Thread.CurrentThread.CurrentCulture.ToString().ToLower().Equals("en-us"))
                    {
                        c.Outcome = "Dead";
                    }
                    break;
                case "3":
                    if (System.Threading.Thread.CurrentThread.CurrentCulture.ToString().ToLower().Equals("fr-fr"))
                    {
                        c.Outcome = "Inconnu";
                    }
                    else if (System.Threading.Thread.CurrentThread.CurrentCulture.ToString().ToLower().Equals("en-us"))
                    {
                        c.Outcome = "Unknown";
                    }
                    break;
            }

            c.DistrictResidence = row["Districtresidence"].ToString();
            c.DistrictReporting = row["Districts"].ToString();

            if (!String.IsNullOrEmpty(row["Semaine"].ToString()))
            {
                c.EpiWeek = int.Parse(row["Semaine"].ToString());
            }

            if (!String.IsNullOrEmpty(row["FirstSaveTime"].ToString()))
            {
                c.DateRecordCreated = DateTime.Parse(row["FirstSaveTime"].ToString());
            }

            if (!String.IsNullOrEmpty(row["LastSaveTime"].ToString()))
            {
                c.DateRecordUpdated = DateTime.Parse(row["LastSaveTime"].ToString());
            }

            if (!String.IsNullOrEmpty(row["DateDebut"].ToString()))
            {
                c.DOB = DateTime.Parse(row["DateDebut"].ToString());
            }

            c.EPID = row["EpidShow"].ToString();
            c.FirstName = row["Prenom"].ToString();
            c.LastName = row["NomPrenom"].ToString();
            c.NameOfParent = row["NomParent"].ToString();
            c.Sex = row["Sexe"].ToString();
            c.UniqueKey = int.Parse(row["UniqueKey"].ToString());
            c.UrbanRural = row["UrbanRural"].ToString();
            c.Guid = row["t.GlobalRecordId"].ToString();
            c.LPPerformed = row["PonctionLombaire"].ToString();
            c.HealthFacility = row["FormationSanitaire"].ToString();
        }

        private Case CreateCaseFromGuid(string guid)
        {
            CaseViewModel c = new CaseViewModel();

            Query selectQuery = Database.CreateQuery("SELECT * " +
                CaseForm.FromViewSQL + " " +
                "WHERE [t.GlobalRecordId] = '" + guid + "'");
            DataTable dt = Database.Select(selectQuery);

            if (dt.Rows.Count == 1)
            {
                DataRow row = dt.Rows[0];
                LoadCaseData(row, c);
            }
            return c.Case;
        }

        private void AddCase(Case newCase)
        {
            if (CaseCollection == null)
                return;

            CaseViewModel newCaseVM = new CaseViewModel { Case = newCase };
            CaseCollection.Add(newCaseVM);

            this.Search(LastSearchTerm);
        }

        public ICommand UpdateOrAddCase { get { return new RelayCommand<string>(UpdateOrAddCaseExecute); } }
        void UpdateOrAddCaseExecute(string caseGuid)
        {
            if (CaseCollection == null)
                return;

            Case c = CreateCaseFromGuid(caseGuid);
            CaseViewModel newCaseVM = null;
            bool found = false;
            foreach (var iCase in CaseCollection)
            {
                if (iCase.Guid == caseGuid)
                {
                    newCaseVM = iCase;
                    iCase.Update.Execute(c);
                    found = true;
                    break;
                }
            }

            if (!found)
            {
                AddCase(c);
            }

            List<CaseViewModel> duplicates = GetDuplicateCasesBasedOnID();

            if (duplicates.Count > 0)
            {
                if (DuplicateIdDetected != null)
                {
                    DuplicateIdDetected(this, new DuplicateIdDetectedArgs(duplicates));
                }
            }
        }

        public void UpdateSite(string siteCode)
        {
            foreach (SiteMergeStatusViewModel svm in SiteCollection)
            {
                if (svm.SiteCode == siteCode)
                {
                    svm.LastMerged = DateTime.Now;
                    svm.DaysElapsed = 0;

                    foreach (XmlNode node in SiteXmlData.ChildNodes[0].ChildNodes)
                    {
                        if (node.Attributes["Code"].Value.Equals(siteCode))
                        {
                            node.ChildNodes[0].InnerText = svm.LastMerged.Value.Ticks.ToString();
                        }
                    }

                    string path = Path.GetDirectoryName(
                     Assembly.GetAssembly(typeof(Common)).CodeBase);

                    SiteXmlData.Save(System.IO.Path.Combine(path.Replace("file:\\", string.Empty), @"Projects\Menafrinet\SiteMergeStatus.xml"));
                    break;
                }
            }
        }

        private void LoadSiteMergeData()
        {
            SiteCollection = new ObservableCollection<SiteMergeStatusViewModel>();
            
            Districts districts = new Districts();
            Regions regions = new Regions();

            XmlDocument xmlDoc = new XmlDocument();
            SiteXmlData = xmlDoc;
            string path = Path.GetDirectoryName(
                     Assembly.GetAssembly(typeof(Common)).CodeBase);

            xmlDoc.Load(System.IO.Path.Combine(path, "Projects/Menafrinet/SiteMergeStatus.xml"));

            foreach (XmlNode node in xmlDoc.ChildNodes[0].ChildNodes)
            {
                SiteMergeStatusViewModel siteVM = new SiteMergeStatusViewModel();
                siteVM.SiteName = node.Attributes["Name"].Value;
                siteVM.SiteCode = node.Attributes["Code"].Value;
                string region = node.Attributes["Region"].Value;
                string regionCode = node.Attributes["RegionCode"].Value;

                District d = new District(siteVM.SiteName, siteVM.SiteCode, region);
                districts.Sites.Add(d);

                Region r = new Region(region, regionCode);
                bool found = false;
                foreach (Locations.ISite site in regions.Sites)
                {
                    if (site.Name == region)
                    {
                        found = true;
                        break;
                    }
                }
                if (!found)
                {
                    regions.Sites.Add(r);
                }

                if (node.ChildNodes.Count > 0 && node.ChildNodes[0].InnerText != null)
                {
                    long ticks = long.Parse(node.ChildNodes[0].InnerText.ToString());
                    siteVM.LastMerged = new DateTime(ticks);
                }

                if (siteVM.LastMerged.HasValue)
                {
                    DateTime now = DateTime.Now;

                    TimeSpan ts = now - siteVM.LastMerged.Value;
                    siteVM.DaysElapsed = (int)ts.TotalDays;
                }
                SiteCollection.Add(siteVM);
            }

            SiteTypes.Add(districts);
            SiteTypes.Add(regions);
            SiteTypes.Add(new MoH());
        }

        /// <summary>
        /// Populates the data helper's internal collection of cases
        /// </summary>
        protected void PopulateCollections()
        {
            LoadSiteMergeData();

            System.Diagnostics.Stopwatch swMain = new System.Diagnostics.Stopwatch();
            swMain.Start();

            System.Diagnostics.Stopwatch sw1 = new System.Diagnostics.Stopwatch();
            sw1.Start();
            DataTable CaseTable = GetCasesTable(); // time-consuming
            sw1.Stop();
            System.Diagnostics.Debug.Print("CaseTable Get: " + sw1.Elapsed.TotalMilliseconds.ToString());

            DataView CaseView = new DataView(CaseTable, String.Empty, String.Empty, DataViewRowState.CurrentRows);

            System.Diagnostics.Stopwatch sw3 = new System.Diagnostics.Stopwatch();
            sw3.Start();
            CaseView.Sort = "EPID_CASNO";
            foreach (DataRowView rowView in CaseView)
            {
                CaseViewModel c = new CaseViewModel();
                LoadCaseData(rowView.Row, c);
                CaseCollection.Add(c);
            }
            sw3.Stop();
            System.Diagnostics.Debug.Print("Load Case Data: " + sw3.Elapsed.TotalMilliseconds.ToString());

            if (CaseDataPopulated != null)
            {
                CaseDataPopulated(this, new CaseDataPopulatedArgs());
            }
            
            //List<CaseViewModel> duplicates = GetDuplicateCasesBasedOnID();

            //if (duplicates.Count > 0)
            //{
            //    if (DuplicateIdDetected != null)
            //    {
            //        DuplicateIdDetected(this, new DuplicateIdDetectedArgs(duplicates));
            //    }
            //}

            FlagDuplicateRecords();

            // Check for valid IDs
            List<string> invalidIds = new List<string>();

            foreach (CaseViewModel caseVM in CaseCollection)
            {
                string actualID = caseVM.EPID;
            }

            if (InvalidIdDetected != null && invalidIds.Count > 0)
            {
                InvalidIdDetected(this, new InvalidIdDetectedArgs(invalidIds));
            }

            swMain.Stop();
            System.Diagnostics.Debug.Print("PopulateCollections END: " + swMain.Elapsed.TotalMilliseconds.ToString());

            FilteredCaseCollection.Clear();
            foreach (CaseViewModel caseVM in CaseCollection)
            {
                FilteredCaseCollection.Add(caseVM);
            }

            TaskbarProgressState = System.Windows.Shell.TaskbarItemProgressState.None;
        }

        /// <summary>
        /// Sets up the database for the first time.
        /// </summary>
        private void SetupDatabase()
        {
            Database = Project.CollectedData.GetDatabase();
            foreach (View view in Project.Views)
            {
                // ugly hack... this is needed to get the view object without needing to specify the view name (which may differ between countries)
                // and because we can't just say Project.Views[0]
                CaseForm = view;
                break;
            }

            #region Set meta DB info

            if (!Database.ColumnExists("metaDbInfo", "Menafrinet"))
            {
                List<Epi.Data.TableColumn> tcList = new List<Epi.Data.TableColumn>();
                tcList.Add(new Epi.Data.TableColumn("Menafrinet", GenericDbColumnType.Boolean, false));

                foreach (Epi.Data.TableColumn tableColumn in tcList)
                {
                    Database.AddColumn("metaDbInfo", tableColumn);
                }

                Query updateQuery = Database.CreateQuery("UPDATE metaDbInfo SET [Menafrinet] = true");
                Database.ExecuteNonQuery(updateQuery);

                FileInfo fi = new FileInfo(this.ProjectPath);
                DirectoryInfo di = fi.Directory;

                string exports = System.IO.Path.Combine(di.FullName, "DataExports");
                string imports = System.IO.Path.Combine(di.FullName, "DataImports");
                string importArchives = System.IO.Path.Combine(imports, "Archives");

                System.IO.Directory.CreateDirectory(exports);
                System.IO.Directory.CreateDirectory(imports);
                System.IO.Directory.CreateDirectory(importArchives);

                if (InitialSetupRun != null)
                {
                    InitialSetupRun(this, new EventArgs());
                }
            }
            #endregion // Set meta DB info
        }
    }
}
